/*
 * jlb
 */
package com.jlb.user.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baidu.fsg.uid.UidGenerator;
import com.jlb.core.base.BaseDAO;
import com.jlb.core.base.BaseSVImpl;
import com.jlb.core.entity.Page;
import com.jlb.core.exceptions.*;
import com.jlb.core.tools.security.Md5;
import com.jlb.count.entity.Count;
import com.jlb.count.service.CountSV;
import com.jlb.jlb.dao.JlbOreLogDAO;
import com.jlb.jlb.entity.JlbOreLog;
import com.jlb.jlb.entity.JlbOreLogEvent;
import com.jlb.jlb.entity.JlbOreLogType;
import com.jlb.jlb.entity.TransferType;
import com.jlb.miner.dao.MinerItemDAO;
import com.jlb.miner.entity.MinerItem;
import com.jlb.my.dao.MyGroupDAO;
import com.jlb.my.entity.MyGroup;
import com.jlb.ore.dao.OreRecordDAO;
import com.jlb.ore.entity.OreRecord;
import com.jlb.platform.entity.PlatformAccount;
import com.jlb.setting.dao.SettingDAO;
import com.jlb.setting.entity.Setting;
import com.jlb.star.dao.StarLevelDAO;
import com.jlb.star.entity.StarLevel;
import com.jlb.star.entity.StarLevelRule;
import com.jlb.user.dao.*;
import com.jlb.user.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service("userJlbSV")
@Slf4j
public class UserJlbSVImpl extends BaseSVImpl<UserJlb, Long> implements UserJlbSV {

    @Autowired
    private CountSV countSV;

    @Autowired
    private JlbOreLogDAO jlbOreLogDAO;

    @Autowired
    private MinerItemDAO minerItemDAO;

    @Autowired
    private OreRecordDAO oreRecordDAO;

    @Autowired
    private StarLevelDAO starLevelDAO;

    @Autowired
    private UserJlbDAO userJlbDAO;

    @Autowired
    private UserOreDAO userOreDAO;

    @Autowired
    private MyGroupDAO myGroupDAO;


    @Autowired
    private UserDAO userDAO;

    @Autowired
    private UserSV userSV;

    @Autowired
    private UserMinerWorkRecordDAO userMinerWorkRecordDAO;

    @Autowired
    private UserMinerDAO userMinerDAO;

    @Autowired
    private SettingDAO settingDAO;


    @Resource
    private UidGenerator uidGenerator;

    @Override
    protected BaseDAO getBaseDAO() {
        return userJlbDAO;
    }

    /**
     * 保存account对象
     *
     * @param entity 实体
     * @throws BaseException
     */
    @Override
    public void save(UserJlb entity) throws BaseException {
        entity.setCode(String.valueOf(uidGenerator.getUID()));
        super.save(entity);
    }

    /**
     * 加载一个对象UserJlb
     *
     * @param id * @param code 编码
     * @return UserJlb
     */
    @Override
    public UserJlb load(java.lang.Long id, java.lang.String code) {
        if (id == null && code == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Ilegal_Param);
        }

        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        return userJlbDAO.load(param);
    }

    /**
     * 加载一个对象UserJlb 通过id
     *
     * @param id
     * @return UserJlb
     */
    @Override
    public UserJlb loadById(java.lang.Long id) {
        if (id == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Ilegal_Param);
        }
        return userJlbDAO.loadById(id);
    }

    /**
     * 加载一个对象UserJlb 通过code
     *
     * @param code 编码
     * @return UserJlb
     */
    @Override
    public UserJlb loadByCode(java.lang.String code) {
        if (code == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Ilegal_Param);
        }
        return userJlbDAO.loadByCode(code);
    }


    /**
     * 根据主键id,oldStates 共同更新 UserJlb 的状态到newState状态
     *
     * @param id
     * @param newState  新状态
     * @param oldStates 旧状态集合
     */
    @Override
    public void updateStateById(java.lang.Long id, UserJlbState newState, UserJlbState... oldStates) {
        if (id == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Ilegal_Param);
        }
        if (newState == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Ilegal_Param);
        }
        if (oldStates == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Ilegal_Param);
        }
        userJlbDAO.updateStateById(id, new Date(), newState, oldStates);
    }

    /**
     * 根据主键code,oldStates 共同更新 UserJlb 的状态到newState状态
     *
     * @param code      编码
     * @param newState  新状态
     * @param oldStates 旧状态集合
     */
    @Override
    public void updateStateByCode(java.lang.String code, UserJlbState newState, UserJlbState... oldStates) {
        if (code == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Ilegal_Param);
        }
        if (newState == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Ilegal_Param);
        }
        if (oldStates == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Ilegal_Param);
        }
        userJlbDAO.updateStateByCode(code, new Date(), newState, oldStates);
    }

    /**
     * 根据主键id 更新 UserJlb 的状态到另一个状态
     *
     * @param id
     * @param state 状态
     */
    @Override
    public void updateById(java.lang.Long id, UserJlbState state) {
        if (id == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Ilegal_Param);
        }
        userJlbDAO.updateById(id, state, new Date());
    }

    /**
     * 根据主键code 更新 UserJlb 的状态到另一个状态
     *
     * @param code  编码
     * @param state 状态
     */
    @Override
    public void updateByCode(java.lang.String code, UserJlbState state) {
        if (code == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Ilegal_Param);
        }
        userJlbDAO.updateByCode(code, state, new Date());
    }


    /**
     * 删除对象UserJlb
     *
     * @param id * @param code 编码
     * @return UserJlb
     */
    @Override
    public void delete(java.lang.Long id, java.lang.String code) {
        if (id == null && code == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Ilegal_Param);
        }
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        userJlbDAO.delete(param);
    }


    /**
     * 查询UserJlb分页
     *
     * @param userJlb 对象
     * @param offset  查询开始行
     * @param limit   查询行数
     * @return List<UserJlb>
     */
    @Override
    public List<UserJlb> list(UserJlb userJlb, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }

        if (limit < 0) {
            limit = Page.limit;
        }

        Map<String, Object> map = null;
        if (userJlb != null) {
            map = JSON.parseObject(JSON.toJSONString(userJlb, SerializerFeature.WriteDateUseDateFormat));
        } else {
            map = new HashMap<>();
        }
        return userJlbDAO.list(map, new RowBounds(offset, limit));
    }

    @Override
    public int count(UserJlb userJlb) {
        Map<String, Object> map = null;
        if (userJlb != null) {
            map = JSON.parseObject(JSON.toJSONString(userJlb, SerializerFeature.WriteDateUseDateFormat));
        } else {
            map = new HashMap<>();
        }
        return userJlbDAO.count(map);
    }

    /**
     * 查询UserJlb分页
     *
     * @param id     * @param code  编码
     * @param offset 查询开始行
     * @param limit  查询行数
     * @return List<UserJlb>
     */
    @Override
    public List<UserJlb> list(java.lang.Long id, java.lang.String code, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }

        if (limit < 0) {
            limit = Page.limit;
        }
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        return userJlbDAO.list(param, new RowBounds(offset, limit));
    }

    @Override
    public int count(java.lang.Long id, java.lang.String code) {
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        return userJlbDAO.count(param);
    }

    /**
     * 已挖到
     * 1.查看矿机状态
     * 2.修改为已挖到状态
     * 3.记录日志
     * 4.自动收割金兰宝
     *
     * @param userCode 用户编码
     */
    @Override
    public void digOut(String userCode) {
        //1.查看矿机状态
        UserMiner userMiner = userMinerDAO.loadByUserCode(userCode);
        if (userMiner == null) {
            throw new UserMinerException(BaseException.BaseExceptionEnum.Result_Not_Exist);
        }
        if (UserMinerState.getEnum(userMiner.getState()) == UserMinerState.Stop) {
            throw new UserMinerException(BaseException.BaseExceptionEnum.State_Error);
        }

        Map<String, Object> params = new HashedMap();
        params.put("userCode", userCode);
        UserJlb userJlb = userJlbDAO.load(params);
        if (userJlb == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Jlb_Not_Exist);
        }

        if (UserJlbState.Frozen == UserJlbState.getEnum(userJlb.getState())) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Jlb_Frozen_Error);
        }

        if (UserJlbMinerState.Dig_Out == UserJlbMinerState.getEnum(userJlb.getDigInJlbState())) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Jlb_State_Error);
        }

        //2.修改为已挖到状态
        userJlb.setDigInJlbState(UserJlbMinerState.Dig_Out.name());
        userJlbDAO.update(userJlb);

        //3.记录日志
        userMinerWorkRecordDAO.insert(new UserMinerWorkRecord(userCode, userMiner.getMinerCode(), userJlb.getDigInJlb(), UserJlbMinerState.Dig_Out.name()));

//        //4.自动收割金兰宝
//        this.harvest(userCode);
    }

    /**
     * 挖金兰宝
     * 1.查询所有需要收割金兰宝的账户
     * 2.挖金兰宝
     * 3.上级矿石计算
     * 4.记录日志
     */
    @Override
    public void mining() {
        //1.查询所有需要收割金兰宝的账户
        Map<String, Object> param = new HashMap<>();
        param.put("state", UserMinerState.Working.name());
        List<UserMiner> userMinerList = userMinerDAO.list(param);
        //2.挖金兰宝
        userMinerDAO.mining();
        //3.上级矿石计算
        //解冻被jlb小于0的动态收益
        userMinerList.forEach(userMiner -> {
            param.clear();
            param.put("userCode", userMiner.getUserCode());
            param.put("state", UserOreState.Stop.name());
            UserOre userOre = userOreDAO.load(param);
            if (userOre != null) {
                param.clear();
                param.put("userCode", userMiner.getUserCode());
                param.put("state", UserJlbState.Active.name());
                UserJlb userJlb = userJlbDAO.load(param);
                //启动被jlb不足时停止的动态收益
                if (userJlb.getJlb() > 0) {
                    User user = userDAO.loadByCode(userMiner.getUserCode());

                    Map<String, Object> paramStar = new HashMap<>();
                    int oreIncomeUpperLimit = 0;
                    if (user.getStar() != 0) {
                        paramStar.put("starLevel", String.valueOf(user.getStar()));
                        StarLevel starLevel = starLevelDAO.load(paramStar);
                        if (starLevel != null) {
                            MinerItem minerItem = minerItemDAO.loadByCode(userMiner.getMinerCode());
                            int price = Integer.parseInt(minerItem.getPrice());
                            oreIncomeUpperLimit = price * Integer.parseInt(starLevel.getMultiple());
                            if (userOre.getLayerTotalOre() < oreIncomeUpperLimit) {
                                userOre.setState(UserOreState.Active.name());
                                userOreDAO.update(userOre);
                            }
                        }
                    }

                }
            }
        });

        //计算上级动态收益
        List<OreRecord> oreRecordList = new ArrayList<>();
        userMinerList.forEach(userMiner -> {
            this.calPreLevelOre(userMiner.getUserCode(), Integer.parseInt(userMiner.getDailyIncome()), oreRecordList);
        });

        if (!oreRecordList.isEmpty()) {
            oreRecordDAO.batchInsert(oreRecordList);
        }

        //4.记录日志
        List<UserMinerWorkRecord> userMinerWorkRecordList = new ArrayList<>();
        userMinerList.forEach(userMiner -> {
            userMinerWorkRecordList.add(new UserMinerWorkRecord(userMiner.getUserCode(), userMiner.getMinerCode(), userMiner.getDailyIncome(), UserJlbMinerState.Recorded.name()));
        });
        userMinerWorkRecordDAO.batchInsert(userMinerWorkRecordList);

    }

    /**
     * 收割[已挖到]金兰宝
     * 1.查询已经挖到的金兰宝
     * 2.收割金兰宝
     * 3.记录日志
     * 4.检查矿机是否上线，如果上线停止矿机
     * 5.给上级收益矿石
     *
     * @param userCode 用户编码
     */
    @Override
    public void harvest(String userCode) {
        //1.查询已经挖到的金兰宝
        UserMiner userMiner = userMinerDAO.loadByUserCode(userCode);
        if (userMiner == null) {
            throw new UserMinerException(BaseException.BaseExceptionEnum.Miner_Not_Exist);
        }
        if (UserMinerState.getEnum(userMiner.getState()) == UserMinerState.Stop) {
            throw new UserMinerException(BaseException.BaseExceptionEnum.Miner_Stop);
        }
        Map<String, Object> params = new HashedMap();
        params.put("userCode", userCode);
        UserJlb userJlb = userJlbDAO.load(params);
        if (userJlb == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Jlb_Not_Exist);
        }
        if (UserJlbState.Frozen == UserJlbState.getEnum(userJlb.getState())) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Jlb_Frozen_Error);
        }
        if (UserJlbMinerState.getEnum(userJlb.getDigInJlbState()) != UserJlbMinerState.Dig_Out) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Jlb_State_Error);
        }

        //2.收割金兰宝
        userJlb = this.harvest(userJlb);

        //统计
        countSV.saveOrUpdate(new Count(String.valueOf(userJlb.getJlb()), null, null, null));

        //3.记录日志
        userMinerWorkRecordDAO.insert(new UserMinerWorkRecord(userCode, userMiner.getMinerCode(), userJlb.getDigInJlb(), UserJlbMinerState.Recorded.name()));

        //4.检查矿机是否上限制，如果上线停止矿机
        UserOre userOre = userOreDAO.loadByUserCode(userCode);
        if (userJlb.getDigInTotalJlb() >= Float.parseFloat(userMiner.getUpperLimit())) {
            userMinerDAO.updateByUserCode(userCode, UserMinerState.Stop.name(), new Date());
            //开始新一轮挖矿
            UserJlb userJlbObj = userJlbDAO.load(params);
            userJlbObj.setDigInJlbState(UserJlbMinerState.Recorded.name());
            userJlbDAO.update(userJlbObj);

            if (userOre != null && UserOreState.getEnum(userOre.getState()) == UserOreState.Active) {
                userOre.setState(UserOreState.Stop.name());
                userOreDAO.update(userOre);
            }
        } else {
            //开始新一轮挖矿
            UserJlb userJlbObj = userJlbDAO.load(params);
            userJlbObj.setDigInJlbState(UserJlbMinerState.Dig_In.name());
            userJlbDAO.update(userJlbObj);

            //启动被jlb不足时停止的动态收益
            if (userJlbObj.getJlb() > 0) {
                User user = userDAO.loadByCode(userCode);
                Map<String, Object> paramStar = new HashMap<>();
                paramStar.put("starLevel", String.valueOf(user.getStar()));
                StarLevel starLevel = starLevelDAO.load(paramStar);
                MinerItem minerItem = minerItemDAO.loadByCode(userMiner.getMinerCode());
                Integer price = Integer.parseInt(minerItem.getPrice());
                Integer oreIncomeUpperLimit = price * Integer.parseInt(starLevel.getMultiple());
                if (userOre != null && UserOreState.getEnum(userOre.getState()) == UserOreState.Stop && userOre.getLayerTotalOre() < oreIncomeUpperLimit) {
                    userOre.setState(UserOreState.Active.name());
                    userOreDAO.update(userOre);
                }
            }

        }

        //5.给上级收益矿石
        List<OreRecord> oreRecordList = new ArrayList<>();
        this.calPreLevelOre(userCode, Float.parseFloat(userJlb.getDigInJlb()), oreRecordList);
        if (!oreRecordList.isEmpty()) {
            oreRecordDAO.batchInsert(oreRecordList);
        }
    }


    /**
     * 1.查询全局是否启用全收益天数
     * 2.判断是否在全收益天数是否小于等于0
     * 3.根据矿机分割商城上限限制，计算商城金兰宝总数
     *
     * @param userJlb UserJlb
     * @return
     */
    private UserJlb harvest(UserJlb userJlb) {
        UserMiner userMiner = userMinerDAO.loadByUserCode(userJlb.getUserCode());
        if (userMiner == null) {
            throw new UserMinerException(BaseException.BaseExceptionEnum.Miner_Not_Exist);
        }
        if (UserMinerState.getEnum(userMiner.getState()) == UserMinerState.Stop) {
            throw new UserMinerException(BaseException.BaseExceptionEnum.Miner_Stop);
        }

        MinerItem minerItem = minerItemDAO.loadByCode(userMiner.getMinerCode());
        if (minerItem == null) {
            throw new MinerItemException(BaseException.BaseExceptionEnum.Miner_Not_Exist);
        }

        //矿机日收益
        float dailyIncome = Float.parseFloat(minerItem.getDailyIncome());

        //超过限制就进行分割商城收益
        if (userJlb.getDigInTotalJlb() >= minerItem.getSeparateLimit()) {
            Setting setting = settingDAO.loadByK(Setting.Key.Mall_Separate_Rate.name());
            float rate = Float.parseFloat(setting.getV()) / 100;

            //实际产出
            float diginJlb = dailyIncome * rate;

            //商城金兰宝收益
            float mallJlb = dailyIncome - diginJlb;

            userJlb.setJlb((int) (userJlb.getJlb() + diginJlb));
            userJlb.setMallTotalJlb((int) ((userJlb.getMallTotalJlb() == null ? 0 : userJlb.getMallTotalJlb()) + mallJlb));
        } else {
            userJlb.setJlb((int) (userJlb.getJlb() + dailyIncome));
            userJlb.setMallTotalJlb(0);
        }

        userJlb.setDigInTotalJlb((userJlb.getDigInTotalJlb() == null ? 0 : userJlb.getDigInTotalJlb()) + (int) dailyIncome);
        userJlb.setRelease(0);
        userJlb.setDigInJlbState(UserJlbMinerState.Recorded.name());
        userJlbDAO.update(userJlb);
        return userJlb;
    }

    //计算上级收益矿石数量
    private void calPreLevelOre(String userCode, float jlb, List<OreRecord> oreRecordList) {
        Map<String, Object> param = new HashMap<>();
        param.put("subUserCode", userCode);
        List<MyGroup> myGroupList = myGroupDAO.list(param);

        myGroupList.forEach(myGroup -> {
            User user = userDAO.loadByCode(myGroup.getUserCode());
            if (UserState.getEnum(user.getState()) != UserState.Active) {
                return;
            }

            //动态收益停止的跳出
            UserOre userOre = userOreDAO.loadByUserCode(user.getCode());
            if (userOre == null) {
                return;
            }
            if (UserOreState.getEnum(userOre.getState()) == UserOreState.Stop) {
                return;
            }

            //查询对应上级的星级及规则
            Map<String, Object> paramStar = new HashMap<>();
            paramStar.put("starLevel", String.valueOf(user.getStar()));
            StarLevel starLevel = starLevelDAO.load(paramStar);
            if (starLevel != null) {
                if (starLevel.getStarLevelRuleList() != null && !starLevel.getStarLevelRuleList().isEmpty()) {
                    for (StarLevelRule starLevelRule : starLevel.getStarLevelRuleList()) {
                        if (String.valueOf(starLevelRule.getLevel()).equals(String.valueOf(myGroup.getSubLevel()))) {

                            //计算上级应该收的矿石量
                            float rate = Float.parseFloat(starLevelRule.getRate()) / 100;
                            float income = rate * jlb;
                            log.debug("income:" + income);
                            userOre.setLayerTotalOre((int) (userOre.getLayerTotalOre() + income));
                            userOre.setRefineTotalOre((int) (userOre.getRefineTotalOre() + income));
                            userOreDAO.update(userOre);
                            //记录日志
                            oreRecordList.add(new OreRecord(String.valueOf(uidGenerator.getUID()), user.getCode(),
                                    userCode, myGroup.getSubLevel(), starLevelRule.getRate(), (int) income));

                            //检查是否需要停止动态收益
                            if (!user.getCode().equals(PlatformAccount.PlatformAccountEnum.Platform.name())) {
                                UserMiner userMinerLoad = userMinerDAO.loadByUserCode(user.getCode());
                                if (userMinerLoad != null) {
                                    MinerItem minerItem = minerItemDAO.loadByCode(userMinerLoad.getMinerCode());
                                    Integer price = Integer.parseInt(minerItem.getPrice());
                                    Integer oreIncomeUpperLimit = price * Integer.parseInt(starLevel.getMultiple());
                                    if (userOre.getLayerTotalOre() >= oreIncomeUpperLimit) {
                                        userOre.setUserCode(user.getCode());
                                        userOre.setState(UserOreState.Stop.name());
                                        userOreDAO.update(userOre);
                                    }
                                }
                            }

                        }
                    }
                }
            }

        });


    }

    /**
     * 金兰宝转账
     * 1.检查转出账户的余额
     * 2.检查转入账户的状态
     * 3.用户之间是否可以转账
     * 4.转账
     * 5.记录转账日志
     *
     * @param outUser     转出金兰宝用户编码
     * @param inAccount   转入金兰宝用户账户
     * @param jlb         金兰宝数量
     * @param pinPassword 支付密码
     */
    @Override
    public void transfer(User outUser, String inAccount, Integer jlb, String pinPassword) {
        //交易密码是否正确
        if (!Md5.md5(pinPassword).equals(outUser.getPinPassword())) {
            throw new UserOreException(BaseException.BaseExceptionEnum.Pin_Password_Is_Error);
        }
        Map<String, Object> param = new HashMap<>();
        param.clear();
        param.put("account", inAccount);
        User inUser = userDAO.loadByAccountNotRelation(inAccount);
        if (inUser == null) {
            throw new UserException(BaseException.BaseExceptionEnum.Result_Not_Exist);
        }
        //判断是否给自己转账
        if (outUser.getCode().equals(inUser.getCode())) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Not_Allow_Transfer_Yourself);
        }
        //2.检查转出账户的状态
        param.clear();
        param.put("userCode", outUser.getCode());
        UserJlb outUserJlb = userJlbDAO.load(param);
        if (outUserJlb == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Jlb_Not_Enough_Error);
        }
        if (UserJlbState.getEnum(outUserJlb.getState()) == UserJlbState.Frozen) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Jlb_Frozen_Error);
        }

        if (outUserJlb.getJlb() < jlb) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Jlb_Not_Enough_Error);
        }

        //2.检查转入账户的状态
        UserJlb inUserJlb = this.watchUserJlbAccount(inUser.getCode());
        if (UserJlbState.getEnum(inUserJlb.getState()) == UserJlbState.Frozen) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Jlb_Frozen_Error);
        }

        //3.用户之间是否可以转账
        boolean result = userSV.isAllowTranfer(outUser.getCode(), inUser.getCode());
        if (!result) {
            throw new UserOreException(BaseException.BaseExceptionEnum.Not_Allow_Transfer);
        }
        //4.转账
        //转出
        outUserJlb.setJlb(outUserJlb.getJlb() - jlb);
        userJlbDAO.update(outUserJlb);

        //转入
        inUserJlb.setJlb(inUserJlb.getJlb() + jlb);
        userJlbDAO.update(inUserJlb);

        //5.记录转账日志
        jlbOreLogDAO.insert(new JlbOreLog(outUser.getCode(), inUser.getCode(), jlb, JlbOreLogType.JLB.name(), JlbOreLogEvent.Transfer.name(),
                outUserJlb.getJlb() + jlb, outUserJlb.getJlb(), inUserJlb.getJlb() - jlb, inUserJlb.getJlb()));
    }

    @Override
    public Integer jlbTotal() {
        return userJlbDAO.jlbTotal();
    }

    /**
     * 平台充值或扣除金兰宝
     *
     * @param account      账户
     * @param num          数量
     * @param transferType 转账类型
     */
    @Override
    public void platUpdateJlb(String account, Integer num, TransferType transferType) {
        if (StringUtils.isEmpty(account) || num == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Ilegal_Param);
        }
        User user = userDAO.loadByAccount(account);
        if (user == null) {
            throw new UserJlbException(BaseException.BaseExceptionEnum.Result_Not_Exist);
        }
        //1.查询用户金兰宝账户是否存在，如果不存在，创建账户
        String userCode = user.getCode();
        UserJlb userJlb = this.watchUserJlbAccount(userCode);
        if (transferType == TransferType.Out) {
            int jlb = userJlb.getJlb();
            if (jlb == 0 || jlb < num) {
                throw new UserJlbException(BaseException.BaseExceptionEnum.Jlb_Not_Enough_Error);
            }
        }
        //2.为用户充值或扣除
        if (transferType == TransferType.In) {
            num = num * (-1);
        }
        userJlb.setJlb(userJlb.getJlb() - num);
        userJlbDAO.update(userJlb);
        //添加记录
        if (transferType == TransferType.In) {//充值
            jlbOreLogDAO.insert(new JlbOreLog(PlatformAccount.PlatformAccountEnum.Platform.name(), userCode,
                    num * (-1), JlbOreLogType.JLB.name(), JlbOreLogEvent.Recharge.name(), userJlb.getJlb() + num,
                    userJlb.getJlb(), 0, 0));
        } else {//扣除
            jlbOreLogDAO.insert(new JlbOreLog(userCode, PlatformAccount.PlatformAccountEnum.Platform.name(),
                    num, JlbOreLogType.JLB.name(), JlbOreLogEvent.Deduct.name(), userJlb.getJlb() + num,
                    userJlb.getJlb(), 0, 0));
        }
    }

    /**
     * 查看用户是否有金兰宝账户，如果没有，创建金兰宝账户
     *
     * @param userCode
     * @return
     */
    @Override
    public UserJlb watchUserJlbAccount(String userCode) {
        Map<String, Object> params = new HashedMap();
        params.put("userCode", userCode);
        UserJlb inUserJlb = userJlbDAO.load(params);
        if (inUserJlb == null) {
            inUserJlb = new UserJlb();
            inUserJlb.setUserCode(userCode);
            inUserJlb.setCode(String.valueOf(uidGenerator.getUID()));
            inUserJlb.setJlb(0);
            inUserJlb.setDigInTotalJlb(0);
            inUserJlb.setRelease(0);
            inUserJlb.setDigInJlb("0");
            inUserJlb.setDigInJlbState(UserJlbMinerState.Dig_In.name());
            inUserJlb.setState(UserJlbState.Active.name());
            inUserJlb.setMallTotalJlb(0);
            userJlbDAO.insert(inUserJlb);
        }
        return inUserJlb;
    }


}
